#include "server.h"
#define MCU_timeout 10


pthread_t connToDev_th;
pthread_t connToMcu_th;
pthread_t connToclient_th;
pthread_t connToSql_th;
pthread_t cmd_forward_th;
pthread_t data_forward_th;
pthread_t Mcu_ok_th;
pthread_t Client_ok_th;

void *connToDev (void *arg);		//	网络连接模块
void *connToMcu (void *arg);		//	连接MCU模块
void *connToclient (void *arg);		//	连接客户端模块
void *connToSql (void *arg);		//	连接数据库模块
void *cmd_forward (void *arg);		//	命令转发模块模块
void *data_forward (void *arg);		//	数据转发模块模块
void *Mcu_ok (void *arg);			//	检测mcu是否还活着
void *Client_ok (void *arg);		//	检测client是否还活着
void start_all_modular(void);
void Send_to_MCU(char *p,int start ,int end);
void clean_CMD(void);

struct net_str
{
  int fd;
  int cnt;
};

struct mcu_data
{
  int Temperature;
  int humidity;
  int light;
  int Temperature_threshold;
  int humidity_threshold;
  int light_threshold;
} mcu_data_head[600];
int now_mcudata=0;

volatile int SendClientFlag=0;

void start_all_modular(void)
{
  memset(mcu_data_head,0,sizeof(mcu_data_head));
  
  pthread_create(&connToDev_th,NULL,connToDev,NULL);
  pthread_detach(connToDev_th);	//线程分离	自动回收资源

  pthread_create(&connToSql_th,NULL,connToSql,NULL);
  pthread_detach(connToSql_th);	//线程分离	自动回收资源
}

//  网络连接模块
void *connToDev (void *arg)
{
  int sockfd;
  struct net_str *newfd;
  struct sockaddr_in s_addr, c_addr;
  char buf[BUFLEN];
  socklen_t len_accept;
  int len;
  unsigned int port, listnum;

  /*建立socket*/
  if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1){
    perror("socket");
    exit(errno);
  }else printf("socket create success!\n");

  port = 3389;/*设置服务器端口*/
  listnum = 30;/*设置侦听队列长度*/

  bzero(&s_addr, sizeof(s_addr));
  s_addr.sin_family = AF_INET;
  s_addr.sin_port = htons(port);
  s_addr.sin_addr.s_addr = INADDR_ANY;

  if((bind(sockfd, (struct sockaddr*) &s_addr,sizeof(struct sockaddr))) == -1){
    perror("bind");
    exit(errno);
  }else printf("bind success!\n");
  
  /*侦听本地端口*/
  if(listen(sockfd,listnum) == -1){
    perror("listen");
    exit(errno);
  }else printf("the server is listening!\n");

  while(1) {
_retry:
    bzero(buf,BUFLEN);
    sprintf(buf,"who are you?");
    
    newfd = malloc(sizeof(struct net_str));

    len_accept = sizeof(struct sockaddr);
    if((newfd->fd = accept(sockfd,(struct sockaddr*) &c_addr, &len_accept)) == -1){
      perror("accept");
      exit(errno);
    }else printf("新设备连接%s: %d\n",inet_ntoa(c_addr.sin_addr),ntohs(c_addr.sin_port));

    len = send(newfd->fd,buf,strlen(buf),0);
    if(!(len > 0)) {
      printf("连接断开\n");
      close(newfd->fd);
      free(newfd);
      goto _retry;
    }
    /******接收消息*******/
    bzero(buf,BUFLEN);
    len = recv(newfd->fd,buf,BUFLEN,0);
    newfd->cnt = 7;
    if(len>0) {
      if(strstr(buf,"mcu")>0) {
        clean_CMD();  //清空指令列表
        printf("mcu连接\n");
        pthread_create(&connToMcu_th,NULL,connToMcu,(void *)newfd);
        //线程分离	自动回收资源
        pthread_detach(connToMcu_th);
        pthread_create(&cmd_forward_th,NULL,cmd_forward,(void *)newfd);
        //线程分离	自动回收资源
        pthread_detach(cmd_forward_th);
        pthread_create(&Mcu_ok_th,NULL,Mcu_ok,(void *)newfd);
        //线程分离	自动回收资源
        pthread_detach(Mcu_ok_th);
        sleep(1);
        continue;
      } else if(strstr(buf,"client")>0) {
        printf("client连接\n");
        pthread_create(&connToclient_th,NULL,connToclient,(void *)newfd);
        //线程分离	自动回收资源
        pthread_detach(connToclient_th);
        pthread_create(&data_forward_th,NULL,data_forward,(void *)newfd);
        //线程分离	自动回收资源
        pthread_detach(data_forward_th);
        pthread_create(&Client_ok_th,NULL,Client_ok,(void *)newfd);
        //线程分离	自动回收资源
        pthread_detach(Client_ok_th);
        sleep(1);
        continue;
      } else {
        printf("error buf info,len=%d,->%s<-\n",len,buf);
        close(newfd->fd);
        free(newfd);
        goto _retry;
      }
    } else {
      printf("认证错误,len=%d\n",len);
      close(newfd->fd);
      free(newfd);
      goto _retry;
    }
  }
  return 0;
}


//检测mcu是否还连接
void *Mcu_ok (void *arg)
{
  struct net_str *newfd = (struct net_str *)arg;
  while (newfd->cnt>0)
  {
    newfd->cnt--;
    sleep(1);
  }
  close(newfd->fd);
  printf("mcu超时\n");
  return 0;
}

//  连接MCU模块
void *connToMcu (void *arg)
{
  struct net_str *newfd = (struct net_str *)arg;
  char buf[BUFLEN];
  int len;
  char *start,*end;

  while(1)
  {
    bzero(buf,BUFLEN);
    if(newfd->fd==0) return 0;
    len = recv(newfd->fd,buf,BUFLEN,0);
    newfd->cnt = MCU_timeout;
    if(len<=0)
    {
      newfd->cnt=0;
      printf("MCU断开连接\n");
      close(newfd->fd);
      return 0;
    }
    printf("   mcu数据,len=%d",len);

    /***
     * mcu start %02d,%02d,%02d,%02d,%02d,%02d mcu end
     * mcu start 00,01,02,03,04,05 mcu end
    */
    start = strstr(buf,"mcu start");
    end = strstr(buf,"mcu end");

    if(start!=NULL && end!=NULL)
    {
      /*完整数据*/
      int dat[6];

      dat[0] = (start[10]-'0')*10+start[11]-'0';
      dat[1] = (start[13]-'0')*10+start[14]-'0';
      dat[2] = (start[16]-'0')*10+start[17]-'0';
      dat[3] = (start[19]-'0')*10+start[20]-'0';
      dat[4] = (start[22]-'0')*10+start[23]-'0';
      dat[5] = (start[25]-'0')*10+start[26]-'0';
      printf("\t\t%d %d %d %d %d %d\n",
      dat[0],dat[1],dat[2],dat[3],dat[4],dat[5]);
      mcu_data_head[now_mcudata].Temperature 				= dat[0];
      mcu_data_head[now_mcudata].humidity 				= dat[1];
      mcu_data_head[now_mcudata].light 					= dat[2];
      mcu_data_head[now_mcudata].Temperature_threshold 	= dat[3];
      mcu_data_head[now_mcudata].humidity_threshold 		= dat[4];
      mcu_data_head[now_mcudata].light_threshold 			= dat[5];
      now_mcudata++;
      if(now_mcudata>599)now_mcudata=0;
      SendClientFlag++;
    }
  }
  return 0;
}

//	检测client是否还连接
void *Client_ok (void *arg)
{
  struct net_str *newfd = (struct net_str *)arg;
  while (newfd->cnt>0)
  {
    newfd->cnt--;
    sleep(1);
  }
  close(newfd->fd);
  printf("client超时\n");
  return 0;
}

//  连接客户端模块
void *connToclient (void *arg)
{
  struct net_str *newfd = (struct net_str *)arg;
  char buf[BUFLEN];
  int len;
  char *start,*end;

  while(1)
  {
    bzero(buf,BUFLEN);
    
    if(newfd->fd==0) return 0;
    len = recv(newfd->fd,buf,BUFLEN,0);
    if(len<=0)
    {
      newfd->cnt=0;
      close(newfd->fd);
      printf("客户端断开连接\n");
      return 0;
    }
    newfd->cnt=5;
    printf("client数据,len=%d",len);

    /***
     * client start %d,%d,%d,%d,%d,%d client end
    */ 
    //client start 123,987,234234,0,0,0 client end
    start = strstr(buf,"client start");
    end = strstr(buf,"client end");

    if(start!=NULL && end!=NULL)
    {/*完整数据*/
      int dat[6];
      
      Send_to_MCU(buf,start-buf,end-buf);
      dat[0] = (start[13]-'0')*10+start[14]-'0';
      dat[1] = (start[16]-'0')*10+start[17]-'0';
      dat[2] = (start[19]-'0')*10+start[20]-'0';
      dat[3] = (start[22]-'0')*10+start[23]-'0';
      dat[4] = (start[25]-'0')*10+start[26]-'0';
      dat[5] = (start[28]-'0')*10+start[29]-'0';
      printf("\t\t%d %d %d %d %d %d\n",
      dat[0],dat[1],dat[2],dat[3],dat[4],dat[5]);
    }
  }
  return 0;
}



//  连接数据库模块
void *connToSql (void *arg)
{
  return 0;
}




struct MCU_CMD
{
  struct MCU_CMD *next;  //下一条
  struct MCU_CMD *prev;  //下一条
};

struct MCU_CMD *CMD_head,*CMD_now;

void clean_CMD(void)
{
  for(;;)
  {
    if(CMD_now!=NULL && CMD_now->prev!=NULL)
    {
      CMD_now=CMD_now->prev;
      free(CMD_now->next);
      CMD_now->next = NULL;
    }
    else if(CMD_now!=NULL && CMD_now->prev==NULL)
    {
      free(CMD_now);
      CMD_now = NULL;
      CMD_head = NULL;
    }
    else
    {
      return ;
    }
  }
}

void Send_to_MCU(char *p,int start ,int end)
{
  int len = strlen(p);
  char *forward = malloc(len + 64);
  
  for(int i=0;i<len;i++)
  {
    forward[16+i] = p[i];
  }
  
  

  if(CMD_head==NULL || CMD_now == NULL)
  {
    CMD_head = (struct MCU_CMD *)forward;
    CMD_now = (struct MCU_CMD *)forward;
    CMD_now->next = NULL;
    CMD_now->prev = NULL;
  }
  else
  {
    CMD_now->next = (struct MCU_CMD *)forward;
    CMD_now->next->prev = CMD_now;
    CMD_now = (struct MCU_CMD *)forward;
  }

}

//  命令转发模块模块
void *cmd_forward (void *arg)
{
  struct net_str *newfd = (struct net_str *)arg;
  char *buf;
  int len;

  while (1)
  {
    usleep(1000*200);
    if(CMD_now!=NULL)
    {
      
      buf = ((char *)CMD_now) + 16;
      len = send(newfd->fd,buf,strlen(buf),0);
      if(len<=0)
      {
        printf("断开MCU连接111 len = %d\n",len);
        return 0;
      }
      if(CMD_now->prev!=NULL)
      {
        CMD_now = CMD_now->prev;
        free(CMD_now->next);
        CMD_now->next=NULL;
      }
      else
      {
        CMD_now=NULL;
        CMD_head=NULL;
      }
    }
  }

  return 0;
}




//  数据转发模块
void *data_forward (void *arg)
{
  struct net_str *newfd = (struct net_str *)arg;
  char buf[BUFLEN];

  while (1)
  {
    sleep(1);
    if(newfd->cnt==0)return 0;
    if(SendClientFlag>0)
    {
      char *p;
      int tmp;

      SendClientFlag=0;
      bzero(buf,BUFLEN);
      if(now_mcudata-1<0)
      {
        sprintf(buf,"server start 00,%02d,%02d,%02d,server end",
            mcu_data_head[599].Temperature_threshold,
            mcu_data_head[599].humidity_threshold,
            mcu_data_head[599].light_threshold);
      }
      else
      {
        sprintf(buf,"server start 00,%02d,%02d,%02d,server end",
            mcu_data_head[now_mcudata-1].Temperature_threshold,
            mcu_data_head[now_mcudata-1].humidity_threshold,
            mcu_data_head[now_mcudata-1].light_threshold);
      }
      
      send(newfd->fd,buf,strlen(buf),0);
      usleep(1000*100);

      bzero(buf,BUFLEN);
      sprintf(buf,"server start 01,");
      p = buf + 16;

      for(int op=0;op<600;op++)
      {
        if(now_mcudata-600+op<0)
        {
          tmp = mcu_data_head[now_mcudata-600+op+600].Temperature;
        }
        else
        {
          tmp = mcu_data_head[now_mcudata-600+op].Temperature;
        }
        p[0]=tmp/10%10+'0';
        p[1]=tmp%10+'0';
        p[2]=',';
        p+=3;
      }
      sprintf(p,"server end");
      send(newfd->fd,buf,strlen(buf),0);
      usleep(1000*100);


      bzero(buf,BUFLEN);
      sprintf(buf,"server start 02,");
      p = buf + 16;
      for(int op=0;op<600;op++)
      {
        if(now_mcudata-600+op<0)
        {
          tmp = mcu_data_head[now_mcudata-600+op+600].humidity;
        }
        else
        {
          tmp = mcu_data_head[now_mcudata-600+op].humidity;
        }
        p[0]=tmp/10%10+'0';
        p[1]=tmp%10+'0';
        p[2]=',';
        p+=3;
      }
      sprintf(p,"server end");
      send(newfd->fd,buf,strlen(buf),0);
      usleep(1000*100);

      bzero(buf,BUFLEN);
      sprintf(buf,"server start 03,");
      p = buf + 16;
      for(int op=0;op<600;op++)
      {
        if(now_mcudata-600+op<0)
        {
          tmp = mcu_data_head[now_mcudata-600+op+600].light;
        }
        else
        {
          tmp = mcu_data_head[now_mcudata-600+op].light;
        }
        p[0]=tmp/10%10+'0';
        p[1]=tmp%10+'0';
        p[2]=',';
        p+=3;
      }
      sprintf(p,"server end");
      send(newfd->fd,buf,strlen(buf),0);
      usleep(1000*100);
    }
  }
  return 0;
}



int main(int argc, char **argv)
{
  start_all_modular();

  while (1)
  {
    sleep(1);
  }
  return 0;
}
